/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.web30.semantic.nntp;

import java.text.SimpleDateFormat;
import java.util.Date;
import org.apache.james.mime4j.field.address.Mailbox;
import org.apache.james.mime4j.message.Message;
import org.apache.james.mime4j.parser.Field;
import org.web30.semantic.core.model.MetaData;
import org.web30.semantic.core.model.ResourceAnalyzer;
import org.web30.semantic.sesame.NTriples;

/**
 *
 * @author Xu Tiejun
 */
public class MessageAnalyzer implements ResourceAnalyzer {

    public static final String FOAF_NAMESPACE = "http://xmlns.com/foaf/0.1/";
    public static final String SIOC_NAMESPACE = "http://rdfs.org/sioc/ns#";
    public static final String DC_NAMESPACE = "http://purl.org/dc/elements/1.1/";
    public static final String DEFAULT_ENCODING = "ISO-8859-1";

    public MetaData parseResource(Object obj) {
        if (!(obj instanceof Message)) {
            return null;
        } else {
            StringBuffer temp = new StringBuffer();
            StringBuffer author = this.getAuthorNTriples((Message) obj);
            if(author != null)
                temp = new StringBuffer().append(author);
            StringBuffer msg = this.getMessageNTriples((Message) obj);
            if(msg != null)
                temp.append(msg);
            return new NTriples(temp);
        }
    }

    /**
     * Build one element of N-triples
     * @param namespace  the name space of class or object. such as http://xmlns.com/foaf/0.1/
     * @param e attriubte or object. such as mbox
     * @return
     */
    private String buildElement(String namespace, String e) {
        return new StringBuffer().append("<").append(namespace).append(e).append(">").toString();
    }

    /**
     * Build one triple
     * @param subject  
     * @param predicate
     * @param object
     * @return
     */
    private StringBuffer buildTriple(String subject, String predicate, String object) {
        return new StringBuffer().append(subject).append(" ").append(predicate).append(" ").append(object).append(" .\n");
    }

    /**
     * Build N-triple from MIME message
     * @param newsgroup
     * @param articleId
     * @return
     */
    private String buildMessageUrl(String newsgroup, String articleId) {
        StringBuffer tmp = new StringBuffer().append("<nntp://www.web30core.org:119/").append(newsgroup);
        String id = articleId.substring(articleId.indexOf("<") + 1).trim();
        return tmp.append("/").append(id).toString();
    }

    /**
     * Build url for a person
     * @param name  name of person, maybe nick name
     * @param mbox  mail box of person
     * @return
     */
    private String buildPersonUrl(String name, String mbox) {
        String personId = name + "-" + mbox;
        personId = (new sun.misc.BASE64Encoder()).encode(personId.getBytes());
        StringBuffer tmp = new StringBuffer().append("<http://www.web30core.org/persons/").append(personId).append(">");
        return tmp.toString();
    }
    /**
     * Build element with surround with ""
     * @param element
     * @return
     */
    private String buildElementWithquotation(String element) {
        element = element.trim();
        if(element.startsWith("\"") && element.endsWith("\""))
            return element;
        return "\""+element+"\"";
    }
    /**
     * Get authof information as N-triples
     * @param article
     * @return
     */
    public StringBuffer getAuthorNTriples(Message article) {
        if (article == null) {
            return null;
        }
        StringBuffer triples = new StringBuffer();
        try {
            for (Mailbox box : article.getFrom()) {
                //build person url
                String url = buildPersonUrl(box.getName(), box.getAddress());
                //Build rdf:type
                triples.append(buildTriple(url, "<rdf:type>", buildElement(FOAF_NAMESPACE, "Person")));
                //Build foaf:name
                triples.append(buildTriple(url,
                        buildElement(FOAF_NAMESPACE, "name"),
                        buildElementWithquotation(box.getName())
                        ));
                //Build foaf:mbox
                triples.append(buildTriple(url, 
                        buildElement(FOAF_NAMESPACE, "mbox"),
                        buildElementWithquotation(box.getAddress())
                        ));
                //Build foaf:msnChatID
                if (box.getAddress().indexOf("@hotmail.com") > 0) {
                    triples.append(buildTriple(url,
                            buildElement(FOAF_NAMESPACE, "msnChatID"),
                            buildElementWithquotation(box.getAddress())
                            ));
                }
                //Build foaf:gtalkID
                if (box.getAddress().indexOf("@gmail.com") > 0) {
                    triples.append(buildTriple(url,
                            buildElement(FOAF_NAMESPACE, "gtalkID"),
                            buildElementWithquotation(box.getAddress())
                            ));
                }
                //Build foaf:workplaceHomepage
                if (box.getAddress().indexOf("@nec-as") > 0) {
                    triples.append(buildTriple(url,
                            buildElement(FOAF_NAMESPACE, "workplaceHomepage"),
                            "<http://www.nec-as.com.cn/nec-as/nec-as/>"));
                }
            }
        } catch (Exception e) {
            return null;
        }
        return triples;
    }

    /**
     * Get N-triples from message
     * @param article
     * @return
     */
    public StringBuffer getMessageNTriples(Message article) {
        if (article == null) {
            return null;
        }
        try {
            StringBuffer triples = new StringBuffer();
            //Get message id
            String id = article.getMessageId();
            String newsGroup = article.getHeader().getField("Newsgroups").getBody();
            String url = buildMessageUrl(newsGroup, id);
            //Get message reference
            String[] refers = null;
            Field tmp = article.getHeader().getField("References");
            if (tmp != null) {
                refers = tmp.getBody().split("\\s");
            }
            //Get in reply to
            tmp = article.getHeader().getField("In-Reply-To");
            String replyOf = null;
            if (tmp != null) {
                replyOf = tmp.getBody();
            }
            //DATE FORMAT sample 2009-12-04T00:00:00Z"^^xs:dateTime
            Date date = article.getDate();
            //Build rdf:type
            triples.append(buildTriple(url, "<rdf:type>", buildElement(SIOC_NAMESPACE, "Post")));
            //Build subject
            triples.append(buildTriple(url,
                    buildElement(DC_NAMESPACE, "title"),
                    buildElementWithquotation(article.getSubject())
                    ));
            //Build reference
            if (refers != null) {
                for (String reference : refers) {
                    String tmpUrl = buildMessageUrl(newsGroup, reference);
                    triples.append(buildTriple(url, buildElement(SIOC_NAMESPACE, "references"), tmpUrl));
                }
            }
            //Build replyOf
            if (replyOf != null) {
                String tmpUrl = buildMessageUrl(newsGroup, replyOf);
                triples.append(buildTriple(url, buildElement(SIOC_NAMESPACE, "reply_of"), tmpUrl));
            }
            //Build created timestamp http://purl.org/dc/terms/dateSubmitted
            if (date != null) {
                String DATE_FORMAT = "yyyy-MM-DD'T'HH:mm:ssZ";
                SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
                String temp = sdf.format(date);
                String dateTime = temp.substring(0, temp.length()-2) + ":" + temp.substring(temp.length()-2);
                temp = this.buildElementWithquotation(dateTime);
                temp = temp+"^^<http://www.w3.org/2001/XMLSchema#dateTime>";
                triples.append(buildTriple(url, buildElement(DC_NAMESPACE, "dateSubmitted"), temp));
            }
            return triples;
        } catch (Exception e) {
            return null;
        }
    }
}
